<?php
/**
 * Created by PhpStorm.
 * User: luoshuqi
 * Date: 19-2-18
 * Time: 下午5:30
 */

namespace App\Console\Commands;


use App\Models\SysGroup;
use App\Models\SysOperation;
use App\Models\SysUser;
use Dotenv\Dotenv;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;

class Setup extends Command
{
    protected $signature = 'setup';

    const DDL_CREATE_TABLE = <<< END
CREATE TABLE `sys_users` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `username` varchar(45) NOT NULL COMMENT '用户名',
  `password` char(40) NOT NULL COMMENT '密码',
  `group_id` int(10) unsigned NOT NULL COMMENT '组id',
  `enabled` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否启用',
  `deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
  `updated_at` datetime NOT NULL COMMENT '更新时间',
  `created_at` datetime NOT NULL COMMENT '插入时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username_UNIQUE` (`username`),
  KEY `fk_sys_users_1_idx` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='后台管理员';

CREATE TABLE `sys_groups` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL COMMENT '组名称',
  `operation_ids` text COMMENT '有权限的操作id',
  `deleted_at` datetime DEFAULT NULL COMMENT '删除时间',
  `updated_at` datetime NOT NULL COMMENT '更新时间',
  `created_at` datetime DEFAULT NULL COMMENT '插入时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='后台用户组';

CREATE TABLE `sys_tokens` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `token` char(40) NOT NULL COMMENT '登录token',
  `user_id` int(10) unsigned NOT NULL COMMENT '管理员id',
  `updated_at` datetime NOT NULL COMMENT '更新时间',
  `created_at` datetime NOT NULL COMMENT '插入时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `token_UNIQUE` (`token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='后台登录token';

CREATE TABLE `sys_logs` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL COMMENT '用户id',
  `action` varchar(100) NOT NULL COMMENT '操作',
  `context` text NOT NULL COMMENT '参数',
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='操作日志';

CREATE TABLE `sys_actions` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `action` varchar(100) NOT NULL COMMENT '控制器action',
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `action_UNIQUE` (`action`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='控制器actions';

CREATE TABLE `sys_operations` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(45) NOT NULL COMMENT '操作名称',
  `group` varchar(45) NOT NULL COMMENT '所属分组',
  `actions` varchar(100) NOT NULL COMMENT '操作包含的action',
  `sort` int(11) NOT NULL DEFAULT '1000' COMMENT '显示顺序',
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='后台操作'
END;


    public function handle()
    {
        $this->tableExists() and $this->errorExit('表已经存在');
        DB::unprepared(self::DDL_CREATE_TABLE);

        $key = $this->generateKey();
        $this->substituteKey($key);
        (new Dotenv(app()->basePath()))->overload();
        $key === env('APP_KEY') or $this->errorExit('APP_KEY替换失败');

        Artisan::call('dump-operations');
        $operationIds = SysOperation::query()->pluck('id')->toArray();
        $groupModel = SysGroup::query()->forceCreate([
            'name' => '管理员',
            'operation_ids' => $operationIds
        ]);

        $username = 'root';
        $password = $this->generatePassword();
        SysUser::query()->forceCreate([
            'username' => $username,
            'password' => $password,
            'group_id' => $groupModel['id'],
        ]);

        echo '用户名: ' . $username . PHP_EOL;
        echo '密　码: ' . $password . PHP_EOL;
    }

    public function errorExit(string $message)
    {
        $this->getOutput()->error($message);
        exit(1);
    }

    private function tableExists(): bool
    {
        $sql = 'SHOW TABLES LIKE "sys_users"';
        return !!DB::select($sql);
    }

    private function generateKey(): string
    {
        return md5(microtime(true) . mt_rand());
    }

    private function generatePassword(): string
    {
        $chars = array_merge(range('a', 'z'), range('A', 'Z'), range(0, 9));
        $password = '';
        for ($i = 0; $i < 8; ++$i) {
            $password .= $chars[array_rand($chars)];
        }
        return $password;
    }

    private function substituteKey(string $key)
    {
        $file = app()->basePath('.env');
        $content = file_get_contents($file);
        $content = preg_replace('#(?<=[\r\n]APP_KEY\=).*(?=[\r\n])#', $key, $content);
        file_put_contents($file, $content);
    }
}